//! # 使用
//! ```
//!     use algorithms_fourth::io::writer::BinaryWriter;
//!     use algorithms_fourth::io::reader::BinaryReader;
//!         let mut writer = BinaryWriter::new(64);
//!         writer.writer_bool(true);
//!         writer.writer_bool(false);
//!         writer.writer_u8(2);
//!         writer.write_u32(3);
//!         writer.write_u64(4);
//!         let binding = writer.close();
//!         let mut reader = BinaryReader::new(&binding);
//!         assert!(reader.read_bool());
//!         assert!(!reader.read_bool());
//!         assert_eq!(reader.read_u8(), 2);
//!         assert_eq!(reader.read_u32(), 3);
//!         assert_eq!(reader.read_u64(), 4);
//! ```
use std::collections::VecDeque;

pub struct BinaryReader<'a> {
    data: &'a [u8],
    buffer: VecDeque<bool>,
    index: usize,
}
impl<'a> BinaryReader<'a> {
    pub fn new(data: &'a [u8]) -> Self {
        BinaryReader {
            data,
            buffer: VecDeque::with_capacity(64),
            index: 0,
        }
    }
    pub fn read_bool(&mut self) -> bool {
        if self.buffer.is_empty() {
            self.extract();
        }
        self.buffer.pop_front().unwrap()
    }
    pub fn read_u8(&mut self) -> u8 {
        self.read(8).try_into().unwrap()
    }
    pub fn read_u32(&mut self) -> u32 {
        self.read(32).try_into().unwrap()
    }
    pub fn read_u64(&mut self) -> u64 {
        self.read(64).try_into().unwrap()
    }
    pub fn read(&mut self, bit: usize) -> usize {
        while self.buffer.len() < bit {
            self.extract();
        }
        let mut ans = Self::convert(self.pop());
        for _ in 0..(bit - 1) {
            ans <<= 1;
            ans += Self::convert(self.pop());
        }
        ans
    }
    fn pop(&mut self) -> bool {
        self.buffer.pop_front().unwrap()
    }
    fn convert(it: bool) -> usize {
        if it {
            1
        } else {
            0
        }
    }

    fn extract(&mut self) {
        let it = self.data[self.index];
        for i in (0..8).rev() {
            let a = 1 << i;
            self.buffer.push_back(a & it == a);
        }
        self.index += 1;
    }
}
#[cfg(test)]
mod test {
    use crate::io::writer::BinaryWriter;

    use super::BinaryReader;

    #[test]
    fn test() {
        let mut writer = BinaryWriter::new(64);
        writer.writer_bool(true);
        writer.writer_bool(false);
        writer.writer_u8(2);
        writer.write_u32(3);
        writer.write_u64(4);
        let binding = writer.close();
        let mut reader = BinaryReader::new(binding.as_ref());
        assert!(reader.read_bool());
        assert!(!reader.read_bool());
        assert_eq!(reader.read_u8(), 2);
        assert_eq!(reader.read_u32(), 3);
        assert_eq!(reader.read_u64(), 4);
    }
}
